function UIController(p_ctx)
{
	try
	{
		this.drawing_context = p_ctx? p_ctx : null;
		this.mousePart = null; //part which currently contains mouse cursor

		// registered parts 
		this.getParts = function() { return this.parts; }		
		this.setParts = function(p_parts) { this.parts = p_parts; }
		this.parts = new Array();
		
		// part with current focus 
		this.getActivePart = function() { for (var p=0; p<this.parts.length; p++) if (this.parts[p].getHasFocus()) return this.parts[p]; return null; }
		this.setActivePart = function(p_part) { for (var p=0; p<this.parts.length; p++) this.parts[p].setHasFocus(this.parts[p] == p_part); }
		
		this.registerPart = function (p_part) { this.parts.push(p_part);  }

		this.render = function()
		{
			this.drawing_context.clearRect(0, 0, 10000, 10000);  //clear drawing area
			for (var p=0; p<this.parts.length; p++) this.parts[p].render(); //render all parts in the order in which they were registered
		} 

		this.pointInPartClientArea = function(p_part, p_point) { return (p_part.getLeft() <= p_point.X && (p_part.getLeft()+p_part.getWidth()) >= p_point.X && p_part.getTop() <= p_point.Y && (p_part.getTop()+p_part.getHeight()) >= p_point.Y); }

		this.mouseEventPart = function(p_point) //the part affected by a mouse event at p_point (e.g the part clicked on)
		{
			var part = null;
			for (var p=0; p<this.parts.length; p++) 
			{	
				if  (this.pointInPartClientArea(this.parts[p], p_point)) part = this.parts[p]; //get topmost part that contains event point
			}
			return part;
		}

		this.onClick = function()
		{	
			//alert('uicontroller clicked');
			var point = getMouseCoordinates(event);
			var part = this.mouseEventPart(point);
			//alert('setting active part');
			this.setActivePart(part); //thus, if part is null (i.e. a neutral area is clicked), active part is set to null (i.e. all parts are de-selected)
			if (part)
				if (part.click)
					part.click(point.X - part.getLeft(), point.Y - part.getTop()); // relative coordinates
			this.render();
		}		
		
		this.onMouseMove = function()
		{	
			//alert('ui controller mouse move');
			var point = getMouseCoordinates(event);
			var part = this.mouseEventPart(point);
			//alert('processing mouse out');
			if (this.mousePart) 
				if ((part!= this.mousePart) || (!part)) //previous mouse part has been moved out of
					if (this.mousePart.mouseOut) 
							this.mousePart.mouseOut(); // no need for coordinates
			//alert('processing mouse over');
			if (this.part) 
				if ((part!= this.mousePart) || (!this.mousePart)) //previous mouse part has been moved out of
					if (this.part.mouseOver) 
							this.part.mouseOver(); // no need for coordinates
			this.mousePart = part;
			//alert('calling part mouse move');
			if (part)				
				if (part.mouseMove) 
					part.mouseMove(point.X - part.getLeft(), point.Y - part.getTop()); // relative coordinates
			this.render();
		}
		this.onMouseOut = function()
		{	
			//seems not needed for parts
		}
		this.onMouseOver = function()
		{	
			//seems not needed for parts
		}

		this.onDoubleClick = function()
		{	
			alert('ui controller double click ');
			var point = getMouseCoordinates(event);
			var part = this.mouseEventPart(point);
			this.setActivePart(part); //thus, if part is null (i.e. a neutral area is clicked), active part is set to null (i.e. all parts are de-selected)
			if (part)
				if (part.doubleClick ) 
					part.doubleClick (point.X - part.getLeft(), point.Y - part.getTop()); // relative coordinates
			this.render();
		}

		this.onMouseDown = function()
		{	
			var point = getMouseCoordinates(event);
			var part = this.mouseEventPart(point);
			this.setActivePart(part); //thus, if part is null (i.e. a neutral area is clicked), active part is set to null (i.e. all parts are de-selected)
			if (part)
				if (part.mouseDown) 
					{ part.mouseDown(point.X - part.getLeft(), point.Y - part.getTop()); } // relative coordinates
			this.render();
		}
		this.onMouseUp = function()
		{	
			var point = getMouseCoordinates(event);
			var part = this.mouseEventPart(point);
			if (part)
				if (part.mouseUp) 
					part.mouseUp(point.X - part.getLeft(), point.Y - part.getTop()); // relative coordinates
			this.render();
		}

		this.onKeyPress = function()
		{	
			//alert(event.which);
			var active_part = this.getActivePart();
			if (active_part)
				if (active_part.keyPress) 
					active_part.keyPress(event.which);
			this.render();
		}

		this.onKeyDown = function()
		{	
			//alert(event.which);
			var active_part = this.getActivePart();
			if (active_part)
				if (active_part.keyDown) 
					var ret = active_part.keyDown(event.which); 
			this.render();
			return ret;
		}
		this.onKeyUp = function()
		{	
			//alert(event.which);
			var active_part = this.getActivePart();
			if (active_part)
				if (active_part.keyUp) 
					active_part.keyUp(event.which);
			this.render();
		}	
	}
	catch (exc)
	{
		alert(exc);
	}
}